import { Options } from 'sequelize';
import { Sequelize } from 'sequelize-typescript'
import MyError from '../utils/myError';
import logger from '../utils/logger';
export class DatabaseManager {
    private static manager?: DatabaseManager = null;
    private dbInstance?: Sequelize = null;
    private dbInstanceMap?: Map<string, Sequelize> = new Map<string, Sequelize>();
    private dbConfig?: Options = null;
    private dbConfigs?: Options[] = [];
    private constructor(dbConfig: Options);
    private constructor(dbConfigs: Options[]);
    private constructor(arg: Options & Options[]) {
        if (Array.isArray(arg)) {
            this.dbConfigs = arg;
            return;
        }
        this.dbConfig = arg;
    }
    public static getInstance(dbConfig: Options & Options[]): DatabaseManager {
        if (!DatabaseManager.manager) {
            DatabaseManager.manager = new DatabaseManager(dbConfig);
        }
        return DatabaseManager.manager;
    }
    public async initDbInstance(models: string): Promise<void> {
        if (!this.dbConfig) {
            throw new MyError('db配置错误,请检查');
        }
        try {
            if (this.dbInstance) await this.dbInstance.close()
            this.dbInstance = new Sequelize(this.dbConfig);
            await this.dbInstance.authenticate();
            this.dbInstance.addModels([models]);
            await this.dbInstance.sync();
        } catch (error) {
            throw new MyError(`数据源初始化失败${error}`);
        }
    }
    public async initDbInstances(models: string[]): Promise<void> {
        if (this.dbInstanceMap.size) {
            for (const [databaseName, dbInstance] of this.dbInstanceMap.entries()) {
                await dbInstance.close();
                this.dbInstanceMap.delete(databaseName);
            }
        }
        const databases: string[] = [];
        for (let i = 0; i < this.dbConfigs.length; i++) {
            const config = this.dbConfigs[i];
            if (databases.includes(config.database)) {
                continue;
            }
            databases.push(config.database);
            try {
                const instance = new Sequelize(config);
                await instance.authenticate();
                instance.addModels([models[i]]);
                await instance.sync();
                this.dbInstanceMap.set(config.database, instance);
            } catch (error) {
                throw new MyError(`数据源初始化失败${error}`);
            }
        }
    }
    public async setDbConfig(dbConfig: Options, models: string): Promise<void> {
        this.dbConfig = dbConfig;
        await this.initDbInstance(models);
        logger.info('切换数据源成功')
    }
    public async setDbConfigs(dbConfigs: Options[], models: string[]): Promise<void> {
        this.dbConfigs = dbConfigs;
        await this.initDbInstances(models);
        logger.info('切换数据源成功')
    }
    public getDbConfig(): Options {
        return this.dbConfig;
    }
    public getDbConfigs(): Options[] {
        return this.dbConfigs;
    }
    public getDbInstance(dbName?: string): Sequelize {
        if (dbName) {
            if (!this.dbInstanceMap.size) {
                throw new MyError('请初始化数据源!')
            }
            return this.dbInstanceMap.get(dbName);
        }
        if (!this.dbInstance) {
            throw new MyError('请初始化数据源!')
        }
        return this.dbInstance;
    }
    public getAllDbInstance(): Map<string, Sequelize> {
        if (!this.dbInstanceMap.size) {
            throw new MyError('请先初始化数据源!')
        }
        return this.dbInstanceMap;
    }
    public close(dbName?: string): void {
        if (dbName) {
            this.dbInstanceMap.get(dbName) && this.dbInstanceMap.get(dbName).close();
            return;
        }
        this.dbInstance && this.dbInstance.close()
    }
}
export default DatabaseManager;